﻿using LdtJudge.DataEngine.DataBaseStores;
using LdtJudge.DataEngine.Model.OptimizationModel;
using LdtJudge.DataEngine.Model.XMLConfigModel.OptimzeMode;
using LdtJudge.DataEngine.Model.XMLConfigModel.SameNodeConfigModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace LdtDataEngin.ModuleDetail.BaseModule.MultiFack
{
    /// <summary>
    /// 数据再加工基础类
    /// </summary>
    public abstract class MultiFactBase
    {
        public DataContext dataContext { get; set; }

        public enum SameNodeHandleType
        {
            /// <summary>
            /// 要素分析模式
            /// </summary>
            a,
            /// <summary>
            /// 要素比对模式
            /// </summary>
            b,
        }
        /// <summary>
        /// 通用方法处理
        /// </summary>
        /// <param name="template">要素模板</param>
        /// <param name="personxml">需要处理的对象</param>
        /// <param name="xmlConfigModels">对比的配置</param>
        /// <param name="nodeHandleType">同节点判定类型</param>
        /// <returns></returns>
        public abstract string MultiFactHandleCommon(XmlNode template, Dictionary<Tuple<string, string>, XmlNode> personxml, List<SameNodeXml> xmlConfigModels, SameNodeHandleType nodeHandleType);

        /// <summary>
        /// 进行判断两个节点是否是相同的节点
        /// 如果没有配置，则默认返回合并
        /// </summary>
        /// <param name="xmlConfigModel">配置对象</param>
        /// <param name="no_one">节点1</param>
        /// <param name="no_two">节点2</param>
        /// <param name="nodeHandleType">同节点判定类型</param>
        /// <returns></returns>
        protected bool IsSameNode(SameNodeXml xmlConfigModel, XmlNode no_one, XmlNode no_two, SameNodeHandleType nodeHandleType)
        {
            bool issameNode = true;
            if (xmlConfigModel != null)
            {
                //判断当前的业务类型是否在配置中存在
                var handletype = xmlConfigModel.HandleTypes.FirstOrDefault(m => m.Code.Contains(nodeHandleType.ToString()));
                if (handletype != null)
                {
                    if (handletype.CurrentNote != null && handletype.CurrentNote.Count > 0)
                    {//进行判定当前节点的标识是否为空
                        List<string> notlist = handletype.CurrentNote.Select(a => a.Name).ToList();
                        issameNode = XmlNodeEquals(no_one, no_two, notlist);
                    }
                    //如果当前的节点存在配置，则进行根据配置进行取交集
                    if (!string.IsNullOrWhiteSpace(handletype.ChildNode?.Element) && !string.IsNullOrWhiteSpace(handletype.ChildNode?.Name) && issameNode)
                    {
                        //2018-10-29 ljx 调整同节点判定条件，如果配置的子节点有值且不相同则为不是同节点，否则其他情况都视为是一个节点。
                        //&& !string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Name) && !string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Element)
                        //IssameNode = false;
                        //进行判定当前两个对比的节点是否存在配置的节点
                        //2018-10-30 当同节点判定是，如果该节点配置的标识为当前节点直接子级，需要进行判定当前标识子节点数量，首先进行判定是否数量相同，其次进行判定如果数量相同，则判定所以值不同就不进行合并
                        XmlNodeList onenodelist = no_two.SelectNodes(handletype.ChildNode.Name);
                        XmlNodeList twonodelist = no_one.SelectNodes(handletype.ChildNode.Name);
                        if (onenodelist.Count > 0 && twonodelist.Count > 0)
                        {
                            if (onenodelist.Count != twonodelist.Count)
                            {
                                //如果查询到的节点数量不相同则不进行合并
                                issameNode = false;
                            }
                            else if (onenodelist.Count == twonodelist.Count)
                            {

                                List<string> oneElements = new List<string>();
                                List<string> twoElements = new List<string>();
                                foreach (XmlNode onenode in onenodelist)
                                {
                                    var nodetemponeattribute = onenode.Attributes[handletype.ChildNode.Element];
                                    if (nodetemponeattribute != null)
                                    {
                                        oneElements.Add(nodetemponeattribute.Value);
                                    }
                                }
                                foreach (XmlNode twonode in twonodelist)
                                {
                                    var nodetemptwoattribute = twonode.Attributes[handletype.ChildNode.Element];
                                    if (nodetemptwoattribute != null)
                                    {
                                        twoElements.Add(nodetemptwoattribute.Value);
                                    }
                                }
                                oneElements = oneElements.Distinct().ToList();
                                twoElements = twoElements.Distinct().ToList();
                                if (oneElements.Count == twoElements.Count)
                                {
                                    if (oneElements.Except(twoElements).Count() > 0)
                                    {
                                        //、如果两个集合有差集则表示为节点内容不相同，不进行节点合并
                                        issameNode = false;
                                    }
                                }
                                else
                                {
                                    //、如果两个节点的集合数量内容不相同，则表示不相同，不进行节点合并
                                    issameNode = false;
                                }
                            }
                        }
                    }
                }

            }
            return issameNode;
        }
        ///// <summary>
        ///// 进行判断两个节点是否是相同的节点
        ///// 如果没有配置，则默认返回合并
        ///// </summary>
        ///// <param name="xmlConfigModel">配置对象</param>
        ///// <param name="no_one">节点1</param>
        ///// <param name="no_two">节点2</param>
        ///// <returns></returns>
        //protected bool IsSameNode(OptimizeSameNodeXL xmlConfigModel, XmlNode no_one, XmlNode no_two)
        //{
        //    bool issameNode = true;
        //    if (xmlConfigModel != null)
        //    {
        //        if (xmlConfigModel.Currentnote != null && xmlConfigModel.Currentnote.Count > 0)
        //        {//进行判定当前节点的标识是否为空
        //            List<string> notlist = xmlConfigModel.Currentnote.Select(a => a.name).ToList();
        //            issameNode = XmlNodeEquals(no_one, no_two, notlist);
        //        }
        //        //如果当前的节点存在配置，则进行根据配置进行取交集
        //        if (!string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Element) && !string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Name) && issameNode)
        //        {
        //            //2018-10-29 ljx 调整同节点判定条件，如果配置的子节点有值且不相同则为不是同节点，否则其他情况都视为是一个节点。
        //            //&& !string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Name) && !string.IsNullOrWhiteSpace(xmlConfigModel.OptimizeNode.Element)
        //            //IssameNode = false;
        //            //进行判定当前两个对比的节点是否存在配置的节点
        //            //2018-10-30 当同节点判定是，如果该节点配置的标识为当前节点直接子级，需要进行判定当前标识子节点数量，首先进行判定是否数量相同，其次进行判定如果数量相同，则判定所以值不同就不进行合并
        //            XmlNodeList onenodelist = no_two.SelectNodes(xmlConfigModel.OptimizeNode.Name);
        //            XmlNodeList twonodelist = no_one.SelectNodes(xmlConfigModel.OptimizeNode.Name);
        //            if (onenodelist.Count > 0 && twonodelist.Count > 0)
        //            {
        //                if (onenodelist.Count != twonodelist.Count)
        //                {
        //                    //如果查询到的节点数量不相同则不进行合并
        //                    issameNode = false;
        //                }
        //                else if (onenodelist.Count == twonodelist.Count)
        //                {
        //                    List<string> oneElements = new List<string>();
        //                    List<string> twoElements = new List<string>();
        //                    foreach (XmlNode onenode in onenodelist)
        //                    {
        //                        var nodetemponeattribute = onenode.Attributes[xmlConfigModel.OptimizeNode.Element];
        //                        if (nodetemponeattribute != null)
        //                        {
        //                            oneElements.Add(nodetemponeattribute.Value);
        //                        }
        //                    }
        //                    foreach (XmlNode twonode in twonodelist)
        //                    {
        //                        var nodetemptwoattribute = twonode.Attributes[xmlConfigModel.OptimizeNode.Element];
        //                        if (nodetemptwoattribute != null)
        //                        {
        //                            twoElements.Add(nodetemptwoattribute.Value);
        //                        }
        //                    }
        //                    oneElements.Distinct();
        //                    twoElements.Distinct();
        //                    if (oneElements.Count == twoElements.Count)
        //                    {
        //                        if (oneElements.Except(twoElements).Count() > 0)
        //                        {
        //                            //、如果两个集合有差集则表示为节点内容不相同，不进行节点合并
        //                            issameNode = false;
        //                        }
        //                    }
        //                    else
        //                    {
        //                        //、如果两个节点的集合数量内容不相同，则表示不相同，不进行节点合并
        //                        issameNode = false;
        //                    }
        //                }
        //            }
        //        }
        //    }
        //    return issameNode;
        //}

        /// <summary>
        /// 根据当前节点，返回xmlpath
        /// </summary>
        /// <param name="xmlNode">节点名称</param>
        /// <returns></returns>
        protected string GetXmlPath(XmlNode xmlNode)
        {
            try
            {
                string path = "/" + xmlNode.Name;
                XmlNode parent = xmlNode.ParentNode;
                //循环查找节点的父路径直至到顶级无父路径 则为全路径
                while (parent != null && parent != xmlNode.OwnerDocument)
                {
                    path = "/" + parent.Name + path;
                    parent = parent.ParentNode;
                }
                path = path.TrimStart('/');
                return path;
            }
            catch
            {
                return "";
            }
        }

        /// <summary>
        /// 两个节点进行对比是否为相同的节点
        /// </summary>
        /// <param name="no1">基础节点</param>
        /// <param name="no2">被对比的节点</param>
        /// <param name="note">标识，可以为空，如果为空，则进行全部属性相同对比</param>
        /// <returns></returns>
        protected bool XmlNodeEquals(XmlNode no1, XmlNode no2, string note = "")
        {
            if (string.IsNullOrWhiteSpace(note))
            {
                //如果标识为空，则进行的当前节点的全属性对比
                if (no1.Attributes.Count == no2.Attributes.Count)
                {
                    bool issame = true;
                    foreach (XmlAttribute attr in no1.Attributes)
                    {
                        //如果是序号，则不进行对比
                        if (attr.Name == "序号")
                            continue;

                        if (no2.Attributes[attr.Name] == null || no2.Attributes[attr.Name].Value != attr.Value)
                        {
                            issame = false;
                            break;
                        }
                    }
                    return issame;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if (no1.Attributes[note] != null && no2.Attributes[note] != null)
                {
                    if (no1.Attributes[note].Value == no2.Attributes[note].Value)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    return false;
                }
            }
        }
        /// <summary>
        /// 两个节点进行对比是否为相同的节点
        /// </summary>
        /// <param name="no1">基础节点</param>
        /// <param name="no2">被对比的节点</param>
        /// <param name="noteList">标识列集合</param>
        /// <returns></returns>
        protected bool XmlNodeEquals(XmlNode no1, XmlNode no2, List<string> noteList)
        {
            if (noteList != null && noteList.Count > 0)
            {
                bool issame = true;
                foreach (string note in noteList)
                {
                    if (no1.Attributes[note] != null && no2.Attributes[note] != null)
                    {
                        if (no1.Attributes[note].Value != no2.Attributes[note].Value)
                        {
                            issame = false;
                        }
                    }
                }
                return issame;
            }
            else
            {
                //如果标识为空，则进行的当前节点的全属性对比
                if (no1.Attributes.Count == no2.Attributes.Count)
                {
                    bool issame = true;
                    foreach (XmlAttribute attr in no1.Attributes)
                    {
                        ////如果是序号，则不进行对比
                        //if (attr.Name == "序号")
                        //    continue;

                        if (no2.Attributes[attr.Name] == null || no2.Attributes[attr.Name].Value != attr.Value)
                        {
                            issame = false;
                            break;
                        }
                    }
                    return issame;
                }
                else
                {
                    return false;
                }
            }
        }
        /// <summary>
        /// 将传入的节点返回hashcode
        /// </summary>
        /// <param name="node">XmlNode</param>
        /// <returns></returns>
        protected int GetXmlNodeHashCode(XmlNode node)
        {
            return node.ToString().GetHashCode();
        }

        /// <summary>
        /// 进行去除空节点，且包含节点属性只有一个序号的;
        /// </summary>
        /// <param name="docxml">文档对象</param>
        /// <returns></returns>
        protected XmlDocument EscapeNodeIndexAndBlank(XmlDocument docxml)
        {
            //去除只有序号的节点信息
            docxml = EscapeNodeIndex(docxml);
            //去除空节点
            docxml = EscapeBlank(docxml);

            return docxml;
        }

        /// <summary>
        /// 去除xml中的空节点
        /// </summary>
        /// <param name="second">待去除xml</param>
        /// <returns>取出后的结果</returns>
        protected XmlDocument EscapeBlank(XmlDocument second)
        {
            XmlNodeList blanks = second.SelectNodes("//*[not(attribute::*) and not (child::*)]");//取无属性 无子节点的节点
            while (blanks.Count > 0)
            {
                bool flag = true;
                foreach (XmlNode node in blanks)
                {
                    if (node.ParentNode.ParentNode != null)
                    {
                        node.ParentNode.RemoveChild(node);
                    }
                    else
                    {
                        flag = false;
                    }
                }
                blanks = second.SelectNodes("//*[not(attribute::*) and not (child::*)]");//递归查询
                if (!flag)
                    break;
            }
            return second;
        }
        /// <summary>
        /// 去除xml中的空节点
        /// </summary>
        /// <param name="second">待去除xml</param>
        /// <returns>取出后的结果</returns>
        public XmlDocument EscapeBlank_new(XmlDocument second)
        {
            XmlNodeList blanks = second.SelectNodes("//*[not(attribute::*) and not (child::*)]");//取无属性 无子节点的节点
            while (blanks.Count > 0)
            {
                bool flag = true;
                foreach (XmlNode node in blanks)
                {
                    if (node.ParentNode.ParentNode != null)
                    {
                        node.ParentNode.RemoveChild(node);
                    }
                    else
                    {
                        flag = false;
                    }
                }
                blanks = second.SelectNodes("//*[not(attribute::*) and not (child::*)]");//递归查询
                if (!flag)
                    break;
            }
            return second;
        }
        /// <summary>
        /// 向文档节点插入需要
        /// </summary>
        /// <param name="docxml">文档对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <returns></returns>
        protected XmlNode InsertAllNodeIndexNew(XmlNode docxml, string nodeName)
        {
            if (string.IsNullOrWhiteSpace(nodeName))
            {
                foreach (XmlNode childnode in docxml.FirstChild.ChildNodes)
                {
                    InsertAllNodeIndexNew(docxml.FirstChild, childnode.Name);
                }
            }
            else
            {
                XmlNodeList nodeList = docxml.SelectNodes(nodeName);
                if (nodeList.Count > 0)
                {
                    for (int i = 0; i < nodeList.Count; i++)
                    {
                        XmlNode node = nodeList[i];
                        if (nodeList[i].Attributes["序号"] != null)
                        {
                            nodeList[i].Attributes.Remove(nodeList[i].Attributes["序号"]);
                        }

                        XmlAttribute att = docxml.OwnerDocument.CreateAttribute("序号");
                        att.Value = i.ToString();
                        if (nodeList[i].Attributes.Count > 0)
                        {
                            nodeList[i].Attributes.InsertBefore(att, nodeList[i].Attributes[0]);
                        }
                        else
                        {
                            nodeList[i].Attributes.Append(att);
                        }

                        foreach (XmlNode childnode in node.ChildNodes)
                        {
                            InsertAllNodeIndexNew(node, childnode.Name);
                        }

                    }
                }
            }


            return docxml;
        }


        /// <summary>
        /// xml节点中如果是多个节点插入序号属性 插入的序号有问题
        /// </summary>
        /// <param name="docxml">xml文档</param>
        /// <returns>去除序号后的xml文档</returns>
        protected XmlDocument InsertAllNodeIndex(XmlDocument docxml)
        {
            try
            {
                XmlNodeList sons = docxml.GetElementsByTagName("*");
                foreach (XmlNode node in sons)
                {
                    string path = GetXmlPath(node);
                    if (path.LastIndexOf('/') < 0)
                        continue;//判定是否为根节点
                    XmlNodeList list = docxml.SelectNodes(path);
                    if (list.Count > 0)
                    {
                        for (int i = 0; i < list.Count; i++)
                        {
                            if (list[i].Attributes["序号"] != null)
                            {
                                list[i].Attributes.Remove(list[i].Attributes["序号"]);
                            }

                            XmlAttribute att = docxml.CreateAttribute("序号");
                            att.Value = i.ToString();
                            if (list[i].Attributes.Count > 0)
                            {
                                list[i].Attributes.InsertBefore(att, list[i].Attributes[0]);
                            }
                            else
                            {
                                list[i].Attributes.Append(att);
                            }

                        }
                    }
                }

                return docxml;
            }
            catch (Exception ex)
            {
                return docxml;
            }
        }

        /// <summary>
        /// 去除xml节点中的所有序号属性
        /// </summary>
        /// <param name="docxml">xml文档</param>
        /// <returns>去除序号后的xml文档</returns>
        protected XmlDocument EscapeAllNodeIndex(XmlDocument docxml)
        {
            try
            {

                XmlNodeList sons = docxml.GetElementsByTagName("*");
                foreach (XmlNode node in sons)
                {
                    if (node.Attributes["序号"] != null)
                    {
                        node.Attributes.Remove(node.Attributes["序号"]);
                    }
                }
                return docxml;
            }
            catch
            {
                return docxml;
            }
        }
        /// <summary>
        /// 去除xml节点中的序号属性,当前节点只有一个属性值 
        /// </summary>
        /// <param name="docxml">xml文档</param>
        /// <returns>去除序号后的xml文档</returns>
        protected XmlDocument EscapeNodeIndex(XmlDocument docxml)
        {
            try
            {

                XmlNodeList sons = docxml.GetElementsByTagName("*");
                foreach (XmlNode node in sons)
                {
                    if (node.Attributes["序号"] != null && node.Attributes.Count == 1)
                    {
                        node.Attributes.Remove(node.Attributes["序号"]);
                    }
                }
                return docxml;
            }
            catch
            {
                return docxml;
            }
        }


        /// <summary>
        /// 去除xml节点中的序号属性,当前节点只有一个属性值 
        /// </summary>
        /// <param name="docxml">xml文档</param>
        protected void EscapeNodeIndexAndNoChild(XmlNode docxml)
        {
            foreach (XmlNode childnode in docxml.ChildNodes)
            {
                this.EscapeNodeIndexAndNoChild(childnode);
            }

            //去除空节点
            XmlNodeList blanks = docxml.SelectNodes("*[not(attribute::*) and not (child::*)]");//取无属性 无子节点的节点
            foreach (XmlNode node in blanks)
            {
                //node.ParentNode.RemoveChild(node);
                docxml.RemoveChild(node);
            }

            if (docxml.Attributes != null)
            {
                if (docxml.Attributes["序号"] != null && docxml.Attributes.Count == 1 && docxml.ChildNodes.Count == 0)
                {
                    docxml.Attributes.Remove(docxml.Attributes["序号"]);
                }
                else if (docxml.Attributes["id"] != null && docxml.Attributes.Count == 1 && docxml.ChildNodes.Count == 0)
                {
                    docxml.Attributes.Remove(docxml.Attributes["id"]);
                }
            }
        }

        /// <summary>
        /// 去除xml节点中的序号属性
        /// </summary>
        /// <param name="xml">xml文档</param>
        /// <returns>去除序号后的xml文档</returns>
        protected string EscapeNodeIndex(string xml)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(EscapeXml(xml));
                XmlNodeList sons = doc.GetElementsByTagName("*");
                foreach (XmlNode node in sons)
                {
                    if (node.Attributes["序号"] != null)
                    {
                        node.Attributes.Remove(node.Attributes["序号"]);
                    }
                }

                return doc.OuterXml;
            }
            catch
            {
                return xml;
            }
        }

        /// <summary>
        /// 替换xml中的非法字符
        /// </summary>
        /// <param name="sourceXml">xml原文</param>
        /// <returns></returns>
        private string EscapeXml(string sourceXml)
        {
            string result = "";

            result = sourceXml.Replace("&", "&amp;");

            return result;
        }
        /// <summary>
        /// 生成xml的序号
        /// </summary>
        /// <param name="xml">xml文本</param>
        /// <returns>对每个节点按照序号从0开始递增</returns>
        protected string GenerateIndex(string xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(EscapeXml(xml));
            XmlNodeList sons = doc.GetElementsByTagName("*");
            foreach (XmlNode node in sons)
            {
                string path = GetXmlPath(node);
                XmlNodeList list = doc.SelectNodes(path);
                if (list.Count > 0)
                {
                    for (int i = 0; i < list.Count; i++)
                    {
                        if (list[i].Attributes["id"] != null)
                        {
                            list[i].Attributes.Remove(list[i].Attributes["id"]);
                        }

                        XmlAttribute att = doc.CreateAttribute("id");
                        att.Value = i.ToString();
                        list[i].Attributes.Append(att);
                    }
                }
            }

            return doc.OuterXml;

        }


        /// <summary>
        /// 设置文档标记
        /// 要素类型    1=认定要素;2=待认定要素;3=有异议要素;4=认定及待认定要素;
        /// </summary>
        /// <param name="type">类型 ElementType     要素类型    1=认定要素;2=待认定要素;3=有异议要素;4=认定及待认定要素;</param>
        /// <param name="name">人员名称</param>
        /// <param name="suitdegreeid">诉讼地位</param>
        /// <param name="factname">要素名称</param>
        /// <param name="xml">xml文档</param> 
        /// <returns></returns>
        public virtual string SetXmlFlag(string type, string name, string suitdegreeid, string factname, string xml)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            var factnode = doc.SelectSingleNode("//" + factname);
            if (factnode == null)
            {
                factnode = doc.CreateElement(factname);
                doc.FirstChild.AppendChild(factnode);
            }
            if (!string.IsNullOrWhiteSpace(type))
            {
                XmlAttribute facttype = doc.CreateAttribute("要素类型");
                facttype.Value = type;
                factnode.Attributes.Append(facttype);
            }
            //if (!string.IsNullOrEmpty(name))
            //{
            //    XmlNode assertor = doc.CreateElement("主张方");
            //    XmlAttribute namet = doc.CreateAttribute("主张方姓名");
            //    namet.Value = name;
            //    assertor.Attributes.Append(namet);
            //    XmlAttribute suitDegree = doc.CreateAttribute("主张方诉讼地位");
            //    suitDegree.Value = suitdegreeid;
            //    assertor.Attributes.Append(suitDegree);
            //    factnode.InsertBefore(assertor, factnode.ChildNodes[0]);
            //}
            return doc.OuterXml;
        }



    }
}
